package com.common.tools.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.common.api.exception.CommonException;
import com.common.tools.api.dto.ParamDto;
import com.common.tools.api.service.ParamService;
import com.common.tools.dao.ParamMapper;
import com.common.tools.enums.ParamTypeEnum;
import com.common.tools.po.ParamPo;
import com.common.tools.util.ToolsConstant;
import com.common.util.GenerateSequenceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * <p>
 * 参数表服务实现类
 * </p>
 *
 * @author system
 */
@Slf4j
@Service
public class ParamServiceImpl extends ParamService {

    @Autowired
    private ParamMapper paramMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int dels(List<String> idList) {
        try {
            validateSelectedParam(idList);
            log.info("尝试删除的ID列表：{}", JSON.toJSONString(idList));
            List<ParamPo> paramPos = validateSelectedParamByDatabase(idList);
            validateParamPos(paramPos);
            log.info("即将删除的ID列表：{}", JSON.toJSONString(idList));
            paramMapper.deleteBatchIds(idList);
            // 删除过程中无异常返回1
            return 1;
        } catch (Exception e) {
            log.error("删除参数出现异常，{}", e.getMessage());
            throw e;
        }
    }

    private  List<ParamPo> validateSelectedParamByDatabase(List<String> idList) {
        List<ParamPo> paramPoList = paramMapper.selectBatchIds(idList);
        if (CollectionUtils.isEmpty(paramPoList)) {
            throw new CommonException("未查询到要删除的参数信息！");
        }
        return paramPoList;
    }


    private void validateSelectedParam(List<String> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            throw new CommonException("请选择要删除的参数！");
        }
    }


    /**
     * 校验待删除的参数中是否有系统参数
     *     提示：系统参数不允许删除
     */
    private void validateParamPos(List<ParamPo> paramPos) throws CommonException {
        paramPos.stream()
        .filter(paramPo -> isSysParam(paramPo))
        .findAny()
        .ifPresent(paramPo -> {
            String errorMsg = "不允许删除系统内置参数";
            throw new CommonException(errorMsg);
        });
    }


    // 判断是否为系统字典项
    private boolean isSysParam(ParamPo paramPo) {
    	return ParamTypeEnum.sys.getEunmCode().equals(paramPo.getParamType());
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int add(ParamDto dto) {
        try {
            validateAndAddParam(dto);
            // 新增参数信息
            paramMapper.insert(dto);
            return 1;
        } catch (Exception e) {
            log.error("新增参数失败, {}", e.getMessage());
            throw e;
        }
    }

    private void validateAndAddParam(ParamDto dto) {
        // 校验参数
        validateParamDto(dto);
        dto.setParamType(ParamTypeEnum.user.getEunmCode());
        dto.setParamValueType(validateParamType(dto.getParamValueType()));
        // 每次新增参数的时候，校验参数编码paramCode是否唯一
        checkParamCodeUnique(dto.getParamCode());
        // 新增参数的时候，生成该参数的ID
        prepareParamDto(dto);
    }

    private void prepareParamDto(ParamDto dto) {
        if (StringUtils.isBlank(dto.getId())) {
            dto.setId(GenerateSequenceUtil.generateSequenceNo());
            dto.setCreateTime(new Date());
            dto.setUpdateTime(new Date());
        } else {
            dto.setUpdateTime(new Date());
        }
    }

    private void checkParamCodeUnique(String paramCode) {
        boolean exists = paramMapper.exists(Wrappers.lambdaQuery(ParamPo.class)
                .eq(ParamPo::getParamCode, paramCode));
        if (exists) {
            throw new CommonException("参数编码不允许重复！");
        }
    }

    private String validateParamType(String paramValueType) {
        return paramValueType == null ? ToolsConstant.PARAM_VALUE_TYPE : paramValueType;
    }

    private void validateParamDto(ParamDto dto) {
        if (Objects.isNull(dto)) {
            throw new CommonException("参数内容不能为空！");
        }
        validateField(dto.getParamCode(), "参数编码");
        validateField(dto.getParamName(), "参数名称");
        validateField(dto.getParamValue(), "参数值");
    }

    private void validateField(String value, String filedName) {
        if (StringUtils.isBlank(value)) {
            throw new CommonException(filedName + "不能为空！");
        }
    }


    /**
     * 校验要修改的参数是否存在
     * @param paramId
     * @return
     */
    private ParamPo checkParamExist(String paramId) {
        return Optional.ofNullable(paramMapper.selectById(paramId))
                .orElseThrow(() -> new CommonException("当前要修改的参数不存在！"));
    }

    private void checkParamCodeModification(ParamDto paramDto, ParamPo paramPo) {
        checkFieldModification(paramPo.getParamCode(), paramDto.getParamCode(), "参数编码");
        checkFieldModification(paramPo.getParamType(), paramDto.getParamType(), "参数类型");
    }


    private void checkFieldModification(String oldValue, String newValue, String errorMessage) {
        // 方法入参判空已经在上一步做过了
        if (!Objects.equals(oldValue, newValue)) {
            throw new CommonException(errorMessage + "不允许修改！");
        }
    }

    private void validateAndUpdateParam(ParamDto dto) {
        // 校验参数：判空
        validateParamDto(dto);
        dto.setParamValueType(validateParamType(dto.getParamValueType()));
        ParamPo paramPo = checkParamExist(dto.getId());
        checkParamCodeModification(dto, paramPo);
        // 修改参数信息
        prepareParamDto(dto);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int modify(ParamDto dto) {
        try {
            validateAndUpdateParam(dto);
            paramMapper.updateById(dto);
            return 1;
        } catch (Exception e) {
            log.error("修改参数失败, {}", e.getMessage());
            throw e;
        }
    }


    @Override
    public List<String> getSearchKeyList() {
        return Arrays.asList("param_code", "param_name");
    }
}


























